#ifndef _OBJ_HDR_H
#define _OBJ_HDR_H
/*
 * Copyright 2011 Sylvain Bertrand (digital.ragnarok@gmail.com)
 * This fork is protected by the GNU affero GPLv3 with additionnal rights
 * Original code from Advanced Micro Devices, Inc.
 */

/* path->conn/gpu/grph_id, obj->id*/
#define ID_SUB_ID_MASK	0x00ff
#define ID_N_MASK	0x0700
#define ID_RSVD1_MASK	0x0800
#define ID_TYPE_MASK	0x7000
#define ID_RSVD2_MASK	0x8000
                                                  
#define ID_SUB_ID_SHIFT	0x00
#define ID_N_SHIFT	0x08
#define ID_TYPE_SHIFT	0x0c

/* obj_hdr->disp_dev_support and path->disp_dev */
#define DISP_DEV_CRT1_SUPPORT	BIT(0)
#define DISP_DEV_LCD1_SUPPORT	BIT(1)
#define DISP_DEV_TV1_SUPPORT	BIT(2)
#define DISP_DEV_DFP0_SUPPORT	BIT(3)
#define DISP_DEV_CRT2_SUPPORT	BIT(4)
#define DISP_DEV_LCD2_SUPPORT	BIT(5)
#define DISP_DEV_DFP5_SUPPORT	BIT(6)
#define DISP_DEV_DFP1_SUPPORT	BIT(7)
#define DISP_DEV_CV_SUPPORT	BIT(8)
#define DISP_DEV_DFP2_SUPPORT	BIT(9)
#define DISP_DEV_DFP3_SUPPORT	BIT(10)
#define DISP_DEV_DFP4_SUPPORT	BIT(11)

static u32 vals_dfp_support[DFPx_MAX] __attribute__ ((unused)) = {
	DISP_DEV_DFP0_SUPPORT,
	DISP_DEV_DFP1_SUPPORT,
	DISP_DEV_DFP2_SUPPORT,
	DISP_DEV_DFP3_SUPPORT,
	DISP_DEV_DFP4_SUPPORT,
	DISP_DEV_DFP5_SUPPORT
};

struct obj_hdr
{ 
	struct common_tbl_hdr hdr;
	__le16 disp_dev_support; /* list all  the display devices supported */
	__le16 conn_tbl_of;
	__le16 router_tbl_of;
	__le16 encoder_tbl_of;
	/* only available when protection block is independent */
	__le16 protection_tbl_of;
	__le16 path_tbl_of;
} __packed;

struct path
{
	__le16 disp_dev;	/* the display device this path defines */
	__le16 sz;		/* the size of this struct path */
	__le16 conn_id;		/* connector id, path is to this connector  */
	__le16 gpu_id;		/* gpu id, path is from this gpu */
	__le16 grph_ids;	/* from the first grph obj, connected to
				   the gpu, to the last grph obj, connected
				   to the connector */
} __packed;

struct path_tbl
{
	u8 n;
	u8 ver;
	u8 padding[2];
	struct path paths;
} __packed;

/* graphics object type definition */
#define GRPH_TYPE_NONE		0x0
#define GRPH_TYPE_GPU		0x1
#define GRPH_TYPE_ENCODER	0x2
#define GRPH_TYPE_CONN		0x3
#define GRPH_TYPE_ROUTER	0x4
/* deleted */
#define GRPH_TYPE_DISP_PATH	0x6  
#define GRPH_TYPE_GENERIC	0x7

/* connector type object sub id definitions */
#define CONN_SUB_ID_NONE		0x00 
#define CONN_SUB_ID_SINGLE_LINK_DVI_I	0x01
#define CONN_SUB_ID_DUAL_LINK_DVI_I	0x02
#define CONN_SUB_ID_SINGLE_LINK_DVI_D	0x03
#define CONN_SUB_ID_DUAL_LINK_DVI_D	0x04
#define CONN_SUB_ID_VGA			0x05
#define CONN_SUB_ID_COMPOSITE		0x06
#define CONN_SUB_ID_SVIDEO		0x07
#define CONN_SUB_ID_YPbPr		0x08
#define CONN_SUB_ID_D_CONN		0x09
#define CONN_SUB_ID_9PIN_DIN		0x0a  /* supports both cv & tv */
#define CONN_SUB_ID_SCART		0x0b
#define CONN_SUB_ID_HDMI_TYPE_A		0x0c
#define CONN_SUB_ID_HDMI_TYPE_B		0x0d
#define CONN_SUB_ID_LVDS		0x0e
#define CONN_SUB_ID_7PIN_DIN		0x0f
#define CONN_SUB_ID_PCIE_CONN		0x10
#define CONN_SUB_ID_CROSSFIRE		0x11
#define CONN_SUB_ID_HARDCODE_DVI	0x12
#define CONN_SUB_ID_DP			0x13
#define CONN_SUB_ID_EDP			0x14
#define CONN_SUB_ID_MXM			0x15
#define CONN_SUB_ID_LVDS_EDP		0x16

/* encoder object sub id definitions */
#define ENCODER_SUB_ID_NONE			0x00 

/* radeon class display hardware */
#define ENCODER_SUB_ID_INTERNAL_LVDS		0x01
#define ENCODER_SUB_ID_INTERNAL_TMDS1		0x02
#define ENCODER_SUB_ID_INTERNAL_TMDS2		0x03
#define ENCODER_SUB_ID_INTERNAL_DAC1		0x04
#define ENCODER_SUB_ID_INTERNAL_DAC2		0x05	/* tv/cv dac */
#define ENCODER_SUB_ID_INTERNAL_SDVOA		0x06
#define ENCODER_SUB_ID_INTERNAL_SDVOB		0x07

/* external third party encoders */
#define ENCODER_SUB_ID_SI170B			0x08
#define ENCODER_SUB_ID_CH7303			0x09
#define ENCODER_SUB_ID_CH7301			0x0a
#define ENCODER_SUB_ID_INTERNAL_DVO1		0x0b    /* from radeon hdw */
#define ENCODER_SUB_ID_EXTERNAL_SDVOA		0x0c
#define ENCODER_SUB_ID_EXTERNAL_SDVOB		0x0d
#define ENCODER_SUB_ID_TITFP513			0x0e
#define ENCODER_SUB_ID_INTERNAL_LVTM1		0x0f    /* not used for radeon */
#define ENCODER_SUB_ID_VT1623			0x10
#define ENCODER_SUB_ID_HDMI_SI1930		0x11
#define ENCODER_SUB_ID_HDMI_INTERNAL		0x12
#define ENCODER_SUB_ID_ALMOND			0x22
#define ENCODER_SUB_ID_TRAVIS			0x23
#define ENCODER_SUB_ID_NUTMEG			0x22
/* kaleidoscope (kldscp) class display hardware (internal) */
#define ENCODER_SUB_ID_INTERNAL_KLDSCP_TMDS1	0x13
#define ENCODER_SUB_ID_INTERNAL_KLDSCP_DVO1	0x14
#define ENCODER_SUB_ID_INTERNAL_KLDSCP_DAC1	0x15
#define ENCODER_SUB_ID_INTERNAL_KLDSCP_DAC2	0x16	/* cv/tv and crt */
#define ENCODER_SUB_ID_SI178			0X17	/* external tmds */
#define ENCODER_SUB_ID_MVPU_FPGA		0x18	/* mvpu fpga chip */
#define ENCODER_SUB_ID_INTERNAL_DDI		0x19
#define ENCODER_SUB_ID_VT1625			0x1a
#define ENCODER_SUB_ID_HDMI_SI1932		0x1b
#define ENCODER_SUB_ID_DP_AN9801		0x1c
#define ENCODER_SUB_ID_DP_DP501			0x1d
#define ENCODER_SUB_ID_INTERNAL_UNIPHY0		0x1e
#define ENCODER_SUB_ID_INTERNAL_KLDSCP_LVTMA	0x1f
#define ENCODER_SUB_ID_INTERNAL_UNIPHY1		0x20
#define ENCODER_SUB_ID_INTERNAL_UNIPHY2		0x21

#define ENCODER_SUB_ID_GENERAL_EXTERNAL_DVO	0xff

/* each object has this structure */    
struct obj
{
	__le16 id;
	__le16 src_dst_tbl_of;
	__le16 rec_of;		/* this pointing to a bunch of records defined
				   later on */
	__le16 rsvd;
} __packed;

/*
 * above 4 object table offset pointing to a bunch of objects all have this
 * structure     
 */
struct obj_tbl
{
	u8 n;
	u8 padding[3];
	struct obj objs;
} __packed;

/* some inline helpers */
static inline u8 id_decode_sub_id(u16 id)
{
	return (id & ID_SUB_ID_MASK) >> ID_SUB_ID_SHIFT;
}

static inline u8 id_decode_n(u16 id)
{
	return (id & ID_N_MASK) >> ID_N_SHIFT;
}

static inline u8 id_decode_type(u16 id)
{
	return (id & ID_TYPE_MASK) >> ID_TYPE_SHIFT;
}

static inline s8 trans(u16 id)
{
	switch (id_decode_sub_id(id)) {
	case ENCODER_SUB_ID_INTERNAL_UNIPHY0:
		return 0;	
	case ENCODER_SUB_ID_INTERNAL_UNIPHY1:
		return 1;
	case ENCODER_SUB_ID_INTERNAL_UNIPHY2:
		return 2;
	}
	unreachable();
}

static inline u8 link_type(u16 id)
{
	if (id_decode_n(id) == 2)
		return 1;/* transmitter secondary link B/D/F */
	else
		return 0;/* transmitter primary link A/C/E */
}

static inline u8 to_link(unsigned i)
{
	return i & 1;
}

static inline u8 to_trans(unsigned i)
{
	return (i & ~1) / 2;
}

/* XXX: the following is not used yet */

struct atb_disp_ext_obj_path
{
	u16 dev_tag;		/* supported device */
	u16 sz;			/* the sz of atb_disp_object_path */
	u16 conn_obj_id;	/* connector object id  */
	u16 gpu_obj_id;		/* gpu id */
	u16 graphic_obj_ids[2];	/* graphic_obj_ids[0]: gpu internal encoder
				   graphic_obj_ids[1]: external encoder */
} __packed;



/* src_dst_tbl_offset pointing to this structure */
struct atb_src_dst_tbl_for_one_obj
{
	u8 num_of_src;
	u16 src_obj_id[1];
	u8 num_of_dst;
	u16 dst_obj_id[1];
} __packed;
#endif /* _OBJ_HDR_H */
